package com.jblog.common.util;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.Random;

import javax.imageio.ImageIO;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class Captcha extends HttpServlet {

    private static final long serialVersionUID = 1L;
    
    private static final int WIDTH = 100;
    private static final int HEIGHT = 40;
    public static final String CAPTCHA = "captcha";

    private Random rand = new Random();

    /**
     * 生成随机颜色
     */
    private Color randColor(int start, int end) {
        int randNum;
        if (start > 255)
            start = 255;
        if (end > 255)
            end = 255;
        if (start > end)
            randNum = start - end;
        else
            randNum = end - start;
        int r = start + rand.nextInt(randNum);
        int g = start + rand.nextInt(randNum);
        int b = start + rand.nextInt(randNum);
        return new Color(r, g, b);
    }

    /**
     * 着色\旋转\缩放
     */
    private void coloredAndRotation(String code, int i, Graphics g) {
        /** 着色 **/
        g.setColor(new Color(20 + rand.nextInt(110), 20 + rand.nextInt(110),
                20 + rand.nextInt(110)));
        /** 旋转 **/
        Graphics2D g2d = (Graphics2D) g;
        AffineTransform trans = new AffineTransform();
        trans.rotate(rand.nextInt(45) * 3.14 / 180, 19 * i + 8, 7);
        /** 缩放 **/
        float scaleSize = rand.nextFloat() + 0.7f;
        if (scaleSize > 1f)
            scaleSize = 1f;
        trans.scale(scaleSize, scaleSize);
        g2d.setTransform(trans);
        g.drawString(code, 20 * i + 12, 25);
    }

    /**
     * 生成200条干扰线
     */
    private void randLine(Graphics2D g2d, int width, int height) {
        for (int i = 0; i < 200; i++) {
            int x = rand.nextInt(width - 1);
            int y = rand.nextInt(height - 1);
            int z = rand.nextInt(6) + 1;
            int w = rand.nextInt(12) + 1;

            BasicStroke bs = new BasicStroke(2f, BasicStroke.CAP_BUTT,
                    BasicStroke.JOIN_BEVEL);
            Line2D line = new Line2D.Double(x, y, x + z, y + w);
            g2d.setStroke(bs);
            g2d.draw(line);
        }
    }

    /**
     * 获取随机文字
     */
    private String randCode(int length, Graphics g) {
        String finalWord = "", firstWord = "";
        int tempInt = 0;

        for (int i = 0; i < length; i++) {
            switch (rand.nextInt(2)) {
            case 1:
                tempInt = rand.nextInt(26) + 65;
                break;
            default:
                tempInt = rand.nextInt(10) + 48;
                break;
            }
            firstWord = removeFuzzy(String.valueOf((char) tempInt));
            this.coloredAndRotation(firstWord, i, g);
            finalWord += firstWord;
        }

        return finalWord.toLowerCase();
    }
    
    /**
     * 过滤不容易辨别的文字
     */
    private String removeFuzzy(String c) {
        c = c.replace("0", "W");
        c = c.replace("O", "R");
        c = c.replace("I", "E");
        c = c.replace("1", "P");
        return c;
    }
    
    /**
     * response设置
     */
    private HttpServletResponse responseSetting(HttpServletResponse response) {
        response.setHeader("Pragma", "No-cache");
        response.setHeader("Cache-Control", "No-cache");
        response.setDateHeader("Expires", 0);
        response.setContentType("image/jpeg");
        return response;
    }
    
    /**
     * 图象设置
     */
    private Graphics graphicsSetting(BufferedImage image, int width, int height) {
        Graphics g = image.getGraphics();
        Graphics2D g2d = (Graphics2D) g;
        Font mFont = new Font("arial", Font.BOLD, 30);
        g.fillRect(0, 0, width, height);
        g.setFont(mFont);
        g.setColor(randColor(180, 200));
        randLine(g2d, width, height);
        
        return g;
    }
    
    protected void service(HttpServletRequest request,
            HttpServletResponse response) throws ServletException, IOException {
        
        BufferedImage image = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
        Graphics g = graphicsSetting(image, WIDTH, HEIGHT);

        request.getSession().setAttribute(CAPTCHA, MD5.twice(randCode(4, g)));

        g.dispose();

        ImageIO.write(image, "JPEG", responseSetting(response).getOutputStream());

    }
}
